package conf

import (
	"encoding/json"
	"github.com/nacos-group/nacos-sdk-go/v2/clients"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/config_client"
	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
	"github.com/nacos-group/nacos-sdk-go/v2/vo"
	"go-main/library/conf/dsn"
	"gopkg.in/yaml.v3"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

type ncsCfg struct {
	Network string `dsn:"network"`
	Address string `dsn:"address"`
	Group   string `dsn:"query.group"`
	AppId   string `dsn:"query.appid"`
}

// nc todo
type nc struct {
	value  map[string]interface{}
	client config_client.IConfigClient
}

func NewNcs() (IClient, error) {
	n := &nc{
		value: make(map[string]interface{}),
	}
	ds, err := dsn.Parse(cfgHost)
	if err != nil {
		return nil, err
	}
	var c ncsCfg
	if _, err = ds.Bind(&c); err != nil {
		return nil, err
	}

	if err = n.newClient(&c); err != nil {
		return nil, err
	}
	if err = n.load(&c); err != nil {
		return nil, err
	}
	return n, nil
}

func (n nc) Get(key string) string {
	if v, ok := n.value[key]; ok {
		if s, exist := v.(string); exist {
			return s
		}
	}
	return ""
}

func (n nc) Bind(key string, value interface{}) error {
	if v, ok := n.value[key]; ok {
		if bs, err := json.Marshal(v); err == nil {
			return json.Unmarshal(bs, &value)
		}
	}
	return ErrKeyNotFound
}

func (n *nc) load(c *ncsCfg) error {
	cs, err := n.client.GetConfig(vo.ConfigParam{DataId: c.AppId, Group: c.Group})
	if err != nil {
		return err
	}
	if err = yaml.Unmarshal([]byte(cs), &n.value); err != nil {
		return err
	}
	return nil
}

func (n *nc) newClient(c *ncsCfg) error {
	var sip = "localhost"
	var spo uint64 = 8848
	if c.Network == "" {
		panic("nacos addr and namespace is empty")
	}
	sa := strings.Split(c.Address, ":")
	if len(sa) == 2 {
		sip = sa[0]
		spo, _ = strconv.ParseUint(sa[1], 10, 64)
	}
	sc := []constant.ServerConfig{
		*constant.NewServerConfig(sip, spo),
	}
	//create ClientConfig
	cliCfg := *constant.NewClientConfig(
		constant.WithNamespaceId(""),
		constant.WithTimeoutMs(5000),
		constant.WithNotLoadCacheAtStart(true),
		constant.WithLogDir(filepath.Join(os.TempDir(), "nacos", "log")),
		constant.WithCacheDir(filepath.Join(os.TempDir(), "nacos", "cache")),
		//constant.WithLogLevel("debug"),
	)

	// create config client
	client, err := clients.NewConfigClient(
		vo.NacosClientParam{
			ClientConfig:  &cliCfg,
			ServerConfigs: sc,
		},
	)
	if err != nil {
		return err
	}
	n.client = client
	return nil
}
